//
// Copyright (c) Hisilicon Corporation.  All rights reserved.
// 
// This library is a lite version of MFC
// This library is only for dialog based application and only be tested 
// on windows mobile 6. Be careful to use this library, it isn't a real MFC
//
// Ding Qing 2008-10-30
//

#ifndef  _LFC_H_
#define  _LFC_H_

#ifdef LFC_EXPORTS
#define LFC_API __declspec(dllexport)
#else
#define LFC_API __declspec(dllimport)
#endif


#define MAX_WAITOBJICT_TIME 2000
// Fake macros definition, just for compile ok
#define DEBUG_NEW new
#define DECLARE_DYNAMIC(x)
#define IMPLEMENT_DYNAMIC(x,y)

//----------------------------------------------------------------------------------------------
// Macros copied from afx header file, for message map use
//

// pointer to afx_msg member function
#ifndef AFX_MSG_CALL
#define AFX_MSG_CALL
#endif

struct AFX_MSGMAP_ENTRY;       // declared below after CWnd

struct AFX_MSGMAP
{
	const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
	const AFX_MSGMAP_ENTRY* lpEntries;
};

#define PTM_WARNING_DISABLE \
	__pragma(warning( push )) \
	__pragma(warning( disable : 4867 ))
#define PTM_WARNING_RESTORE \
	__pragma(warning( pop ))


#define DECLARE_MESSAGE_MAP() \
protected: \
	static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
	virtual const AFX_MSGMAP* GetMessageMap() const; \

#define BEGIN_MESSAGE_MAP_TEMPLATE(theClass, type_name, baseClass)			\
	PTM_WARNING_DISABLE														\
	template < typename type_name >											\
	const AFX_MSGMAP* theClass< type_name >::GetMessageMap() const			\
		{ return GetThisMessageMap(); }										\
	template < typename type_name >											\
	const AFX_MSGMAP* PASCAL theClass< type_name >::GetThisMessageMap()		\
	{																		\
		typedef theClass< type_name > ThisClass;							\
		typedef baseClass TheBaseClass;										\
		static const AFX_MSGMAP_ENTRY _messageEntries[] =					\
		{

#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
	PTM_WARNING_DISABLE \
	const AFX_MSGMAP* theClass::GetMessageMap() const \
		{ return GetThisMessageMap(); } \
	const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
	{ \
		typedef theClass ThisClass;						   \
		typedef baseClass TheBaseClass;					   \
		static const AFX_MSGMAP_ENTRY _messageEntries[] =  \
		{

#define END_MESSAGE_MAP() \
		{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
	}; \
		static const AFX_MSGMAP messageMap = \
		{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
		return &messageMap; \
	}								  \
	PTM_WARNING_RESTORE

//----------------------------------------------------------------------------------------------

#include "lfc_def.h"


// Because std lib is not dll-exported, we can't let it present at the header file.
// Use a universal pointer instead, convert it to a needed type at the source file.
typedef DWORD* UNIVERSAL_PTR;

//
// Class CFont
//
class LFC_API CFont
{
public:
    CFont();

    BOOL CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, 
        BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, 
        BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename );

    operator HFONT() const;

protected:
    HFONT  m_hFont;
};


//
// Class CRect
//
class LFC_API CRect
{
public:
    CRect( );
    CRect( int l, int t, int r, int b );
    CRect( LPCRECT lpSrcRect );

    int Width( ) const;
    int Height( ) const;

    operator LPCRECT( ) const;
    operator LPRECT( );

private:
    RECT  m_rect;
};


//
// Class CPoint
//
class LFC_API CPoint
{
public:
    CPoint();
    CPoint(POINT pPoint);
    CPoint(LONG x, LONG y);

    operator POINT() const;

protected:
    POINT  m_point;
};


//
// CDataExchange
//A fake class, don't use it
//
class LFC_API CDataExchange
{
};


//
// Class CWnd
//
// This class don't take part in message handling, it's just a capsulation of window APIs
//
class LFC_API CWnd 
{
public:
    CWnd();
    CWnd(HWND hWnd);
    virtual ~CWnd();

    BOOL ShowWindow( int nCmdShow );
    void MoveWindow ( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE ); 
    void SetFont( CFont* pFont, BOOL bRedraw = TRUE );
    void SetWindowText( LPCTSTR lpszString );
    int MessageBox ( LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK ); 
    UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT, DWORD) );
    BOOL KillTimer( int nIDEvent );
    void Invalidate( BOOL bErase = TRUE );
    BOOL ModifyStyle( DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0 );
    HWND SetFocus( );
    void GetClientRect( LPRECT lpRect ) const;
    void ScreenToClient( LPRECT lpRect ) const;
    BOOL SetForegroundWindow();

    LRESULT SendMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
    BOOL PostMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );

    CWnd* GetDlgItem( int nID ) const;

    // A fake function, don't use it
    virtual void DoDataExchange( CDataExchange* pDX );

public:
    HWND m_hWnd;

protected:
    UNIVERSAL_PTR m_mapDlgItems;

protected:
	static const AFX_MSGMAP* PASCAL GetThisMessageMap();
};


typedef void (AFX_MSG_CALL CWnd::*AFX_PMSG)(void);

struct AFX_MSGMAP_ENTRY
{
	UINT nMessage;   // windows message
	UINT nCode;      // control code or WM_NOTIFY code
	UINT nID;        // control ID (or 0 for windows messages)
	UINT nLastID;    // used for entries specifying a range of control id's
	UINT_PTR nSig;   // signature type (action) or pointer to message #
	AFX_PMSG pfn;    // routine to call (or special value)
};


//
// Class CDialog
//
class LFC_API CDialog : public CWnd
{
public:
    CDialog( UINT nIDTemplate, CWnd* pParentWnd = NULL );
    virtual ~CDialog();

    virtual BOOL OnInitDialog();

    int DoModal();

    void EndDialog( int nResult );

protected:
    static INT_PTR DialogProc(
      HWND hwndDlg,  // handle to dialog box
      UINT uMsg,     // message
      WPARAM wParam, // first message parameter
      LPARAM lParam  // second message parameter
    );

    INT_PTR TheDialogProc(
      UINT uMsg,     // message
      WPARAM wParam, // first message parameter
      LPARAM lParam  // second message parameter
    );

    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnLButtonDown( UINT nFlags, CPoint point );
    afx_msg void OnLButtonUp( UINT nFlags, CPoint point );
    afx_msg void OnMouseMove( UINT nFlags, CPoint point );

private:
    UINT m_nIDTemplate;
    HWND m_hWndParent;
};


//
// Class CListBox
//
// This is not a complete functional MFC CListBox class. 
//
class LFC_API CListBox : public CWnd
{
public:
    int GetCount( ) const;
    DWORD GetItemData( int nIndex ) const;
    int SetItemData( int nIndex, DWORD dwItemData );
    int GetSel( int nIndex ) const;
    int GetCurSel( ) const;
    int SetCurSel( int nIndex) ;
    int SetSel( int nIndex, BOOL bSelect = TRUE );
    int GetSelCount( ) const;
    int GetSelItems( int nMaxItems, LPINT rgIndex ) const;

    int AddString( LPCTSTR lpszItem );
    int DeleteString( UINT nIndex );
    int InsertString( int nIndex, LPCTSTR lpszItem );
};



//
// Class CString
//
// This is not a complete functional MFC CString class. 
// It's purpuse is to make current existing code work.
// Don't use it in new code, use std::(w)string instead.
//
class LFC_API CString
{
public:
    CString( );
    CString( LPCWSTR lpsz );
    CString( LPCSTR lpsz );
    CString( LPCTSTR lpch, int nLength );

    virtual ~CString( );

    int GetLength( ) const;
    BOOL IsEmpty( ) const;
    void Empty( );
    int Delete( int nIndex, int nCount = 1 );

    operator LPCTSTR ( ) const;

    const CString& operator =( const CString& stringSrc );
    const CString& operator =( TCHAR ch );
    const CString& operator =( LPCWSTR lpsz );
    const CString& operator =( LPCSTR lpsz );

    friend CString operator +( const CString& string1, const CString& string2 );
    friend CString operator +( const CString& string, TCHAR ch );
    friend CString operator +( TCHAR ch, const CString& string );
    friend CString operator +( const CString& string, LPCTSTR lpsz );
    friend CString operator +( LPCTSTR lpsz, const CString& string );

    const CString& operator +=( const CString& string );
    const CString& operator +=( TCHAR ch );
    const CString& operator +=( LPCTSTR lpsz );

    friend BOOL operator ==( const CString& s1, const CString& s2 );
    friend BOOL operator ==( const CString& s1, LPCTSTR s2 );
    friend BOOL operator ==( LPCTSTR s1, const CString& s2 );

    void Format( LPCTSTR lpszFormat, ... );

    int Find( TCHAR ch ) const;
    int Find( LPCTSTR lpszSub ) const;
    int ReverseFind( TCHAR ch ) const;

    BOOL LoadString( UINT nID );

protected:
    UNIVERSAL_PTR m_pString;
};


//
// Class CStatic
// 
class LFC_API CStatic : public CWnd
{
public:
    HBITMAP SetBitmap( HBITMAP hBitmap );
    HBITMAP GetBitmap(  );
};


//
// Class CDC
// This class has only a littel part of funcion of MFC CDC
//
// Take notice: Some parameters of methods are not same as MFC, 
//              e.g. GDI object is passed in as handle but not MFC class  
//
class LFC_API CDC
{
public:
    CDC();
    virtual ~CDC();

    // Notice: different from MFC
    HGDIOBJ SelectObject(HGDIOBJ hgdiobj);

    BOOL Rectangle( int x1, int y1, int x2, int y2 );

    CPoint MoveTo( int x, int y ); 
    CPoint MoveTo( POINT point ); 
    BOOL LineTo( int x, int y );
    BOOL LineTo( POINT point );
    COLORREF SetPixel( int x, int y, COLORREF crColor );
    COLORREF SetPixel( POINT point, COLORREF crColor );

    HDC   m_hdc;
};


//
// Class CPaintDC
// A fake class, don't use it
//
class LFC_API CPaintDC : public CDC
{
public:
    CPaintDC(CWnd* pWnd);
    virtual ~CPaintDC();

protected:
    CWnd* m_pWnd;
    PAINTSTRUCT m_paintStruct;
};



//------------------------- Implement AfxGetInstanceHandle ---------------------

// Current instance handle stored in lfc
extern LFC_API HINSTANCE g_currentInstanceHandle;

// App projects use lfc lib should call this macro in its _tmain function and pass its instance handle in
#define LFC_APP_INIT(hInst)  g_currentInstanceHandle = hInst


//Declare a global for projects which include this header
#ifndef LFC_EXPORTS
    extern HINSTANCE  g_lfc_appInstanceHandle;
#endif

// Dll projects use lfc lib should call this macro in one of its .cpp file
#define LFC_DEFINE_INSTANCE()      HINSTANCE  g_lfc_appInstanceHandle;

// Dll projects use lfc lib should call this macro in its DLLMain function and pass its instance handle in
#define LFC_INIT_INSTANCE(hInst)   g_lfc_appInstanceHandle = hInst


#define AfxGetStaticModuleState()  g_lfc_appInstanceHandle

class LFC_API MAINTAIN_INSTANCE
{
public:
    MAINTAIN_INSTANCE(HINSTANCE hAppInst);
    ~MAINTAIN_INSTANCE();

private:
    HINSTANCE m_hPrevInst;
};

// For dll projects, all exported functions should call this macro before they use any lfc function and class
#define AFX_MANAGE_STATE(p)  MAINTAIN_INSTANCE  _maintainInst(p)

LFC_API HINSTANCE AfxGetInstanceHandle();

#endif //_LFC_H_
